#include "GY_NAbstractItemWidget.h"
#include "GY_NTableView.h"

const int GY_NTableView::m_dataRole = Qt::UserRole + 1;
const int GY_NTableView::m_IdRole = Qt::UserRole + 2;

GY_NTableView::GY_NTableView(QWidget *parent) : QTableView(parent) , GY_NStyle(this)
{
    this->setAttribute(Qt::WA_StyledBackground);
    //初始化模型
    m_pViewModel = new QStandardItemModel(0,m_ColumnNumber);
    this->setModel(m_pViewModel);

    //表头设置
    this->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter);
    this->horizontalHeader()->setStretchLastSection(true);
    this->horizontalHeader()->setHighlightSections(false);
    this->setAlternatingRowColors(true);
    this->verticalHeader()->setVisible(false);
    this->setSelectionMode(QAbstractItemView::SingleSelection);
    this->setSelectionBehavior(QAbstractItemView::SelectRows);
    this->horizontalHeader()->setResizeContentsPrecision(QHeaderView::Fixed);
    this->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    this->setEditTriggers(QAbstractItemView::NoEditTriggers);
    this->setShowGrid(false);
}

/**
 * @brief setColumnCount 设置列数量
 * @param value
 */
void GY_NTableView::setColumnCount(int value)
{
    m_ColumnNumber = value;
    m_pViewModel->setColumnCount(m_ColumnNumber);
}
/**
 * @brief addColumnName 添加列名称并添加列
 * @param name
 */
void GY_NTableView::addColumnName(const QString &name)
{
    int targetColumn = m_CoverColumnIndex + (m_hasCheckBox ? 1 : 0);
    m_pViewModel->setHeaderData(targetColumn,Qt::Horizontal,name);
    m_CoverColumnIndex++;
}
/**
 * @brief addRowData 添加行数据
 * @param list
 * @param id
 * @return
 */
int GY_NTableView::addRowData(const QList<QVariant> &list, const QVariant &id)
{
    if(list.length() != m_ColumnNumber){
        qDebug() << "void ControlTableView::addRowData(const QList<QVariant> &list) 注意 list.length() =" << list.length() << "m_ColumnNumber = " << m_ColumnNumber;
    }
    QStandardItem *item = nullptr;
    int row =  m_pViewModel->rowCount();
    for(int i= 0; i < list.length(); i++)
    {
        QVariant data = list.at(i);
        item = new QStandardItem();
        if(i == 0){
            item->setData(QVariant::fromValue<QList<QVariant>>(list), m_dataRole);
            item->setData(id, m_IdRole);
        }
        if(i == 0 && m_hasCheckBox){
            item->setCheckable(true);
            item->setCheckState(Qt::Unchecked);
            m_pViewModel->setItem(row,i,item);
            m_pViewModel->item(row,i)->setTextAlignment(Qt::AlignCenter);
            continue;
        }
        if(m_RegisterInfo.contains(i))
        {
            m_pViewModel->setItem(row,i, item);
            QString className = m_RegisterInfo[i];
            QWidget* pWidget=WidgetReflect::newInstance(className,this);
            if(nullptr==pWidget)
            {
                pWidget=m_RegisterHash.value(className)(this);
                if(nullptr==pWidget)
                {
                    qDebug()<<"实例化自定义控件："<<className<<"失败";
                    item->setText(data.toString());
                    m_pViewModel->setItem(row,i,item);
                    return -1;
                }
            }
            GY_NAbstractItemWidget *itemWidget =  ((GY_NAbstractItemWidget*)pWidget);
            itemWidget->setData(data);
            itemWidget->setPosition(id,i);
            setIndexWidget(m_pViewModel->index(row,i),pWidget);
            connect(itemWidget, &GY_NAbstractItemWidget::controlDataUpdate, this, [=](const QVariant &rowID,const qint32 &columenIndex,const QVariant &data){
                emit clickedCustomWidged(rowID,columenIndex,data,item->index());
            });
        }
        else
        {
            item->setText(data.toString());
            m_pViewModel->setItem(row,i,item);
        }
        m_pViewModel->item(row,i)->setTextAlignment(Qt::AlignCenter);
    }
    this->setRowHeight(row,m_LineHeight);
    return row;
}
/**
 * @brief getModelIndexById 获取某id所在行的 QModelIndex
 * @param id
 * @return
 */
QModelIndex GY_NTableView::getModelIndexById(const QVariant &id)
{
    for(int i = 0 ; i < m_pViewModel->rowCount(); i++){
        QStandardItem *item = m_pViewModel->item(i);
        QVariant idValue = item->data(m_IdRole);
        if(idValue == id){
            return item->index();
        }
    }
    return QModelIndex();
}
/**
 * @brief removeAllData 删除所有
 */
void GY_NTableView::removeAllData()
{
    //只清理表格内容数据
    m_pViewModel->removeRows(0,m_pViewModel->rowCount());
}
/**
 * @brief getRowCount 获取行数
 * @return 返回行数
 */
qint32 GY_NTableView::getRowCount()
{
    return m_pViewModel->rowCount();
}

void GY_NTableView::setLineHeight(int LineHeight)
{
    m_LineHeight = LineHeight;
}

QStandardItemModel *GY_NTableView::getViewModel() const
{
    return m_pViewModel;
}
/**
 * @brief isCheckedAtRow 获取某行是否选中
 * @param row
 * @return
 */
bool GY_NTableView::isCheckedAtRow(int row)
{
    if(row < 0 || row >= m_pViewModel->rowCount()){
        qDebug() << "bool ControlTableView::isCheckedAtRow(int row)  错误的参数 row = " << row;
        return false;
    }

    if(!m_hasCheckBox){
        qDebug() << "bool ControlTableView::isCheckedAtRow(int row)  该表未设置在第0列显示复选框!";
        return false;
    }

    QStandardItem *item = m_pViewModel->item(row, 0);
    return item->checkState() ==  Qt::Checked;
}
/**
 * @brief setHasCheckBox //设置是否将第一列设置成复选框,如果设置成 true, 则在设置列数时，需要加1,插入数据时，第一个数据也需要用 "" 空字符串占位
 * @param value
 */
void GY_NTableView::setHasCheckBox(bool value)
{
    m_hasCheckBox = value;
    if(value){
        m_pViewModel->setHeaderData(0,Qt::Horizontal,"");
    }
}
/**
 * @brief setRowCheckState 设置某行的选中状状态
 * @param row
 * @param isChecked
 */
void GY_NTableView::setRowCheckState(int row, bool isChecked)
{
    if(row < 0 || row >= m_pViewModel->rowCount()){
        qDebug() << "void ControlTableView::setRowCheckState(int row, bool isChecked)  错误的参数 row = " << row;
        return;
    }

    QStandardItem *item = m_pViewModel->item(row, 0);
    Qt::CheckState state = isChecked ?  Qt::Checked : Qt::Unchecked;
    item->setCheckState(state);
}
/**
 * @brief getCheckedDatas 获取选中的数据
 * @param list
 */
void GY_NTableView::getCheckedDatas(QList<QList<QVariant> > &list)
{
    if(!m_hasCheckBox) return;

    for(int i = 0; i < m_pViewModel->rowCount(); ++i){
        if(isCheckedAtRow(i)){
            QStandardItem *item = m_pViewModel->item(i, 0);
            list.push_back(item->data(m_dataRole).value<QList<QVariant>>());
        }
    }
}
/**
 * @brief getDataByModleIndex 获取指定modeindex数据
 * @param index
 * @return
 */
QList<QVariant> GY_NTableView::getDataByModeIndex(const QModelIndex &index){
    QStandardItem *item = m_pViewModel->itemFromIndex(index);
    return item->data(m_dataRole).value<QList<QVariant>>();
}
/**
 * @brief getIdByModeIndex 获取指定ModeIndex的数据ID
 * @param index
 * @return
 */
QVariant GY_NTableView::getIdByModeIndex(const QModelIndex &index){
    QStandardItem *item = m_pViewModel->item(index.row(),0);
    return item->data(m_IdRole);
}
/**
 * @brief getCheckedIds 获取选中的所有id
 * @param list
 */
void GY_NTableView::getCheckedIds(QList<int> &list)
{
    if(!m_hasCheckBox) return;

    for(int i = 0; i < m_pViewModel->rowCount(); ++i){
        if(isCheckedAtRow(i)){
            QStandardItem *item = m_pViewModel->item(i, 0);
            list.push_back(item->data(m_IdRole).toInt());
        }
    }
}

void GY_NTableView::getCheckedIds(QList<QVariant> &list)
{
    if(!m_hasCheckBox) return;

    for(int i = 0; i < m_pViewModel->rowCount(); ++i){
        if(isCheckedAtRow(i)){
            QStandardItem *item = m_pViewModel->item(i, 0);
            list.push_back(item->data(m_IdRole));
        }
    }
}
/**
 * @brief getDataById 通过id获取数据
 * @param id
 * @return
 */
QList<QVariant> GY_NTableView::getDataById(const QVariant &id)
{
    QModelIndex index = getModelIndexById(id);
    if(!index.isValid()){
        qDebug() << "QList<QVariant> ControlTableView::getDataById(int id) 错误的 id =" << id;
        return QList<QVariant>();
    }

    QStandardItem *item = m_pViewModel->item(index.row());
    return item->data(m_dataRole).value<QList<QVariant>>();
}

void GY_NTableView::updateDataById(const QVariant &id, const QList<QVariant> &list)
{
    QModelIndex index = getModelIndexById(id);
    if(!index.isValid()){
        qDebug() << "QList<QVariant> ControlTableView::updateDataById(int id) 错误的 id =" << id;
        return;
    }

    QStandardItem *item = nullptr;
    for(int i= 0; i < list.length(); i++)
    {

        QVariant data = list.at(i);
        item = m_pViewModel->item(index.row(), i);

        if(i == 0){
            item->setData(QVariant::fromValue<QList<QVariant>>(list), m_dataRole);
            item->setData(id, m_IdRole);
        }

        if(i == 0 && m_hasCheckBox){
            item->setCheckable(true);
            item->setCheckState(Qt::Unchecked);
            continue;
        }
        if(m_RegisterInfo.contains(i))
        {
            QWidget* pWidget = indexWidget(item->index());
            if(nullptr==pWidget)
            {
                qDebug()<<"更新自定义控件："<<m_RegisterInfo.value(i)<<"失败";
                item->setText(data.toString());
                return;
            }
            ((GY_NAbstractItemWidget*)pWidget)->setData(data);
        }
        else
        {
            item->setText(data.toString());
        }
    }
}
/**
 * @brief deleteCheckedRow 删除选中行
 */
void GY_NTableView::deleteCheckedRow()
{
    if(!m_hasCheckBox) return;

    int row  = 0;
    while(row < m_pViewModel->rowCount()){
        if(isCheckedAtRow(row)){
            deleteRowByRow(row);
        }else{
            row++;
        }
    }
}
/**
 * @brief deleteRowByRow删除目标行
 * @param row
 */
void GY_NTableView::deleteRowByRow(int row)
{
    if(row < 0 || row >= m_pViewModel->rowCount()){
        qDebug() << "void ControlTableView::deleteRowByIndex(int row)  错误的参数 row = " << row;
        return;
    }
    m_pViewModel->removeRow(row);
}
/**
 * @brief deleteRowById 删除目标ID
 * @param id
 */
void GY_NTableView::deleteRowById(const QVariant &id)
{
    QModelIndex index = getModelIndexById(id);
    if(!index.isValid()){
        qDebug() << "QList<QVariant> ControlTableView::deleteRowById(int id) 错误的 id =" << id;
        return;
    }
    m_pViewModel->removeRow(index.row());
}

